﻿#include "ElementGraphicsView.h"
#include <qevent.h>

#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
    using QTransform = QMatrix;
#endif

ElementGraphicsView::ElementGraphicsView(QWidget *parent)
    :QGraphicsView(parent)
{
    setSliperStyle();
    //connect(this->scene(),&QGraphicsScene::changed,this,[this]());
}

ElementGraphicsView::ElementGraphicsView(QGraphicsScene *scene, QWidget *parent)
    :QGraphicsView(scene,parent)
{
    setSliperStyle();
}

void ElementGraphicsView::scaleView(qreal scaleFactor)
{
    //调用 `transform().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width();` 来计算如果应用当前的缩放因子后，单位正方形（`QRectF(0, 0, 1, 1)`）的宽度会变成多少。
    qreal factor = transform().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width();
    if (factor < 0.3 || factor > 20)
        return;
    mMultiple *= scaleFactor;
    emit zoom(mMultiple);
    scale(scaleFactor, scaleFactor);
}

void ElementGraphicsView::wheelEvent(QWheelEvent *event)
{
    if (event->modifiers() & Qt::ControlModifier) { // 检查是否按下了CTRL键
        // 在这里实现你的CTRL+滚轮逻辑
        // 例如，改变缩放级别而不是滚动
        scaleView(pow(1.1, event->angleDelta().y() / 240.0));
    } else {
        // 如果没有按下CTRL键，则调用基类的wheelEvent进行默认滚动行为
        QAbstractScrollArea::wheelEvent(event);
    }
}

void ElementGraphicsView::paintEvent(QPaintEvent *event)
{
    //! 先绘制 scene() 再绘制边框 防止覆盖
    //! 绘制QGraphicsItem
    QGraphicsView::paintEvent(event);
}

void ElementGraphicsView::drawBackground(QPainter *painter, const QRectF &rect)
{
    QGraphicsView::drawBackground(painter,rect);
    //! 绘制标尺
    QPainter paint(this->viewport());//这行很重要，没有这行的话，绘制出来的东西都会被view里面的其他东西遮住
    //! 每次都重复计算了步长和缩放比例D
    //! 上边 -X轴
    if(mbHorizonRuler)
        drawHorizonRuler(paint);
    //! 左侧 -Y轴
    if(mbVerticalRuler)
        drawVerticalRuler(paint);
    //! 左上 十符号
    if(mbHorizonRuler||mbVerticalRuler)
        drawRuleCross(paint);
    if(mbGridLine)
    {
        //! 竖线
        drawHorGridLine(paint);
        //! 横线
        drawVerGridLine(paint);
    }
}

void ElementGraphicsView::drawHorizonRuler(QPainter &painter)
{
    QPoint lefttop= QPoint(0,0);
    QPoint rigthtop=QPoint(this->width(),0);

    //! 转换成 QGraphicsScene 坐标
    QPointF scene_lefttop=mapToScene(lefttop);
    QPointF scene_rigthtop=mapToScene(rigthtop);

    //! 获取缩放比例 场景宽/视图宽
    float fscale = (scene_rigthtop.x() - scene_lefttop.x())*1.0 / this->width();
    //! 获取步长
    int  nDistance = 100;
    //! 场景里的100对应视图的大小
    nDistance = ((1.0 / fscale * 100) / 10) * 10;
    if (nDistance > 50 && nDistance < 150)
    {
        nDistance = 100;
    }
    if (nDistance >= 150 && nDistance < 200)
    {
        nDistance = 200;
    }
    //    float fDistance = nDistance * 1.0*fscale;

    //! 抹除 上边框 20*width 内容
    painter.setPen(Qt::white);
    painter.setBrush(Qt::white);
    QRect rc(0, 0, this->width(), 20);
    painter.drawRect(rc);
    //! 画下边框线  --为了不出现上 左 右 三条边
    painter.setPen(Qt::black);
    painter.setBrush(Qt::white);
    painter.drawLine(QPoint(20,20),QPoint(this->width(),20));


    QPolygon Rightpoints;
    int nIndex = 0;
    for (int i =0; i < scene_rigthtop.x(); i += nDistance)
    {
        for (int j = 0; j < 10; ++j)
        {
            int nxPt = i + j * (nDistance / 10);
            QPoint viewpointX=mapFromScene(nxPt,0);
            if (viewpointX.x() < 20) //! 为了左上角的符号
                continue;
            int nyPt = 0;
            if (j == 0)
            {
                nyPt = 0;
            }
            else if (j % 5 == 0)
            {
                nyPt = 10;
            }
            else
            {
                nyPt = 15;
            }
            Rightpoints.push_back(QPoint(viewpointX.x(), 20));
            Rightpoints.push_back(QPoint(viewpointX.x(), nyPt));
            Rightpoints.push_back(QPoint(viewpointX.x(), 20));
        }
        if (i >= 0)
        {
            //! 向右偏两像素 避免被遮挡
            QPoint viewpointX=mapFromScene(i,0);
            painter.setBrush(Qt::black);
            painter.drawText(QPoint(viewpointX.x()+2, 14), QString::number(nIndex*nDistance));
        }
        nIndex++;
    }

    //
    QPolygon Leftpoints;
    nIndex = 0;
    for (int i =0; i > scene_lefttop.x(); i -= nDistance)
    {
        for (int j = 0; j < 10; ++j)
        {
            int nxPt = i - j * (nDistance / 10);
            QPoint viewpointX=mapFromScene(nxPt,0);
            if (viewpointX.x() < 20) //! 为了左上角的符号
                continue;
            int nyPt = 0;
            if (j == 0)
            {
                nyPt = 0;
            }
            else if (j % 5 == 0)
            {
                nyPt = 10;
            }
            else
            {
                nyPt = 15;
            }
            Leftpoints.push_front(QPoint(viewpointX.x(), 20));
            Leftpoints.push_front(QPoint(viewpointX.x(), nyPt));
            Leftpoints.push_front(QPoint(viewpointX.x(), 20));
        }
        if (i <= 0)
        {
            QPoint viewpointX=mapFromScene(i,0);
            painter.setBrush(Qt::black);
            //! 向右偏两像素 避免负号被遮挡
            painter.drawText(QPoint(viewpointX.x()+2, 14), QString::number(-nIndex * nDistance));
        }
        nIndex++;
    }

    painter.setPen(Qt::black);
    painter.setBrush(Qt::white);
    painter.drawPolyline(Rightpoints);
    painter.drawPolyline(Leftpoints);
}

void ElementGraphicsView::drawVerticalRuler(QPainter &painter)
{
    QPoint lefttop= QPoint(0,0);
    QPoint leftbtn =QPoint(this->width(),this->height());

    //! 转换成 QGraphicsScene 坐标
    QPointF scene_lefttop=mapToScene(lefttop);
    QPointF scene_leftbtn=mapToScene(leftbtn);


    //! 还是以宽 为标准
    float fscale = (scene_leftbtn.x() - scene_lefttop.x())*1.0 / this->width();

    //! 步长
    int  nDistance = 100;
    nDistance = ((1.0 / fscale * 100) / 10) * 10;
    if (nDistance > 50 && nDistance < 150)
    {
        nDistance = 100;
    }
    if (nDistance >= 150 && nDistance < 200)
    {
        nDistance = 200;
    }

    //! 抹除 左边框 20*height 内容
    painter.setPen(Qt::white);
    painter.setBrush(Qt::white);
    QRect rc(0, 0, 20, this->height());
    painter.drawRect(rc);
    //! 画右边框线  --为了不出现上 左 下 三条边
    painter.setPen(Qt::black);
    painter.setBrush(Qt::white);
    painter.drawLine(QPoint(20,0),QPoint(20,this->height()));

    //! 从 0 往下
    QPolygon Bottompoints;
    int nIndex = 0;
    for (int i = 0; i < scene_leftbtn.y(); i += nDistance)
    {
        for (int j = 0; j < 10; ++j)
        {
            int nyPt = i + j * (nDistance / 10);
            QPoint viewpointY=mapFromScene(QPointF(0,nyPt));
            if (viewpointY.y() < 20)
                continue;
            int nxPt = 0;
            if (j == 0)
            {
                nxPt = 0;
            }
            else if (j % 5 == 0)
            {
                nxPt = 10;
            }
            else
            {
                nxPt = 15;
            }
            Bottompoints.push_back(QPoint(20, viewpointY.y()));
            Bottompoints.push_back(QPoint(nxPt, viewpointY.y()));
            Bottompoints.push_back(QPoint(20, viewpointY.y()));
        }
        if (i >= 0)
        {
            QPoint viewpointY=mapFromScene(QPointF(0,i));
            painter.setBrush(Qt::black);
            QTransform mat;
            mat.translate(2, (viewpointY.y() + 2));
            mat.rotate(90);
            mat.translate(2, -(viewpointY.y() + 2));
            painter.setTransform(mat);
            painter.drawText(QPoint(2, viewpointY.y() + 2), QString::number(nIndex*nDistance));
            painter.resetTransform();
        }
        nIndex++;
    }


    //
    //! 从 0 向上
    QPolygon Toppoints;
    nIndex = 0;
    for (int i = 0; i >= scene_lefttop.y(); i -= nDistance)
    {
        for (int j = 0; j < 10; ++j)
        {
            int nyPt = i - j * (nDistance / 10);
            QPoint viewpointY=mapFromScene(QPointF(0,nyPt));
            if (viewpointY.y() < 20)
                continue;
            int nxPt = 0;
            if (j == 0)
            {
                nxPt = 0;
            }
            else if (j % 5 == 0)
            {
                nxPt = 10;
            }
            else
            {
                nxPt = 15;
            }

            Toppoints.push_front(QPoint(20, viewpointY.y()));
            Toppoints.push_front(QPoint(nxPt, viewpointY.y()));
            Toppoints.push_front(QPoint(20, viewpointY.y()));
        }
        if (i <= 0)
        {
            QPoint viewpointY=mapFromScene(QPointF(0,i));
            painter.setBrush(Qt::black);
            QTransform mat;
            mat.translate(2, (viewpointY.y() + 2));
            mat.rotate(90);
            mat.translate(2, -(viewpointY.y() + 2));
            painter.setTransform(mat);
            painter.drawText(QPoint(2, viewpointY.y() + 2), QString::number(-nIndex * nDistance));
            painter.resetTransform();
        }
        nIndex++;
    }


    //
    //! 绘制线段
    QPen pen(Qt::black, 1, Qt::SolidLine);
    painter.setPen(pen);
    painter.setBrush(Qt::white);
    painter.drawPolyline(Toppoints);
    painter.drawPolyline(Bottompoints);
}

void ElementGraphicsView::drawRuleCross(QPainter &painter)
{
    painter.setBrush(QColor(255, 255, 255, 255));
    painter.setPen(Qt::white);
    painter.drawRect(QRect(0, 0, 20, 20));
    painter.setPen(Qt::DashLine);
    painter.drawLine(QPoint(0, 10), QPoint(20, 10));
    painter.drawLine(QPoint(10, 0), QPoint(10, 20));
    painter.setPen(Qt::SolidLine);
    painter.drawLine(QPoint(0, 20), QPoint(20, 20));
    painter.drawLine(QPoint(20, 0), QPoint(20, 20));
}

void ElementGraphicsView::drawHorGridLine(QPainter &painter)
{
    QPoint lefttop= QPoint(0,0);
    QPoint righttop =QPoint(this->width(),0);

    //! 转换成 QGraphicsScene 坐标
    QPointF scene_lefttop=mapToScene(lefttop);
    QPointF scene_righttop=mapToScene(righttop);


    //! 还是以宽 为标准，scene与view的比例
    float fscale = (scene_righttop.x() - scene_lefttop.x())*1.0 / this->width();

    //! 步长
    int  nDistance = 100;
    nDistance = ((1.0 / fscale * 100) / 10) * 10;
    if (nDistance > 50 && nDistance < 150)
    {
        nDistance = 100;
    }
    if (nDistance >= 150 && nDistance < 200)
    {
        nDistance = 200;
    }

    QPolygon BoldPoints;
    QPolygon ThinPoints;

    //! 从 0 -> ∞
    for (int i = 0; i < scene_righttop.x(); i += nDistance)
    {
        for (int j = 0; j < 10; ++j)
        {
            int nxPt = i + j * (nDistance / 10);
            QPoint viewpointX=mapFromScene(nxPt,0);
            // if (viewpointX.x() < 20)
            //     continue;
            if (j == 0)
            {
                BoldPoints.push_back(QPoint(viewpointX.x(), 0));
                BoldPoints.push_back(QPoint(viewpointX.x(), this->height()));
                BoldPoints.push_back(QPoint(viewpointX.x(), 0));
            }
            else
            {
                ThinPoints.push_back(QPoint(viewpointX.x(), 0));
                ThinPoints.push_back(QPoint(viewpointX.x(), this->height()));
                ThinPoints.push_back(QPoint(viewpointX.x(), 0));
            }
        }
    }

    //! 从 0 到 负无穷
    for (int i = 0; i >= scene_lefttop.x(); i -= nDistance)
    {
        for (int j = 0; j < 10; ++j)
        {
            int nxPt = i - j * (nDistance / 10);
            QPoint viewpointX=mapFromScene(nxPt,0);
            if (j == 0)
            {
                BoldPoints.push_back(QPoint(viewpointX.x(), 0));
                BoldPoints.push_back(QPoint(viewpointX.x(), this->height()));
                BoldPoints.push_back(QPoint(viewpointX.x(), 0));
            }
            else
            {
                ThinPoints.push_back(QPoint(viewpointX.x(), 0));
                ThinPoints.push_back(QPoint(viewpointX.x(), this->height()));
                ThinPoints.push_back(QPoint(viewpointX.x(), 0));
            }
        }
    }

    QPen boldpen(QBrush(QColor(0, 0, 0, 50)), 1);
    painter.setPen(boldpen);
    painter.drawPolyline(BoldPoints);
    QPen thinpen(QBrush(QColor(0, 0, 0, 25)), 1);
    painter.setPen(thinpen);
    painter.drawPolyline(ThinPoints);
}

void ElementGraphicsView::drawVerGridLine(QPainter &painter)
{
    QPoint lefttop= QPoint(0,0);
    QPoint leftbtn =QPoint(this->width(),this->height());

    //! 转换成 QGraphicsScene 坐标
    QPointF scene_lefttop=mapToScene(lefttop);
    QPointF scene_leftbtn=mapToScene(leftbtn);
    //! 还是以宽 为标准
    float fscale = (scene_leftbtn.x() - scene_lefttop.x())*1.0 / this->width();

    //! 步长
    int  nDistance = 100;
    nDistance = ((1.0 / fscale * 100) / 10) * 10;
    if (nDistance > 50 && nDistance < 150)
    {
        nDistance = 100;
    }
    if (nDistance >= 150 && nDistance < 200)
    {
        nDistance = 200;
    }

    QPolygon BoldPoints;
    QPolygon ThinPoints;

    //! 从 0 向下 前进
    for (int i = 0; i < scene_leftbtn.y(); i += nDistance)
    {
        for (int j = 0; j < 10; ++j)
        {
            int nyPt = i + j * (nDistance / 10);
            QPoint viewpointY=mapFromScene(0,nyPt);
            if (j == 0)
            {
                BoldPoints.push_back(QPoint(0, viewpointY.y()));
                BoldPoints.push_back(QPoint(this->width(), viewpointY.y()));
                BoldPoints.push_back(QPoint(0, viewpointY.y()));
            }
            else
            {
                ThinPoints.push_back(QPoint(0, viewpointY.y()));
                ThinPoints.push_back(QPoint(this->width(), viewpointY.y()));
                ThinPoints.push_back(QPoint(0, viewpointY.y()));
            }
        }
    }

    //! 从0 向上 移动
    for (int i = 0; i >= scene_lefttop.y(); i -= nDistance)
    {
        for (int j = 0; j < 10; ++j)
        {
            int nyPt = i - j * (nDistance / 10);
            QPoint viewpointY=mapFromScene(0,nyPt);
            if (j == 0)
            {
                BoldPoints.push_back(QPoint(0, viewpointY.y()));
                BoldPoints.push_back(QPoint(this->width(), viewpointY.y()));
                BoldPoints.push_back(QPoint(0, viewpointY.y()));
            }
            else
            {
                ThinPoints.push_back(QPoint(0, viewpointY.y()));
                ThinPoints.push_back(QPoint(this->width(), viewpointY.y()));
                ThinPoints.push_back(QPoint(0, viewpointY.y()));
            }
        }
    }

    QPen boldpen(QBrush(QColor(0, 0, 0, 50)), 1);
    painter.setPen(boldpen);
    painter.drawPolyline(BoldPoints);
    QPen thinpen(QBrush(QColor(0, 0, 0, 25)), 1);
    painter.setPen(thinpen);
    painter.drawPolyline(ThinPoints);
}

void ElementGraphicsView::setSliperStyle()
{
    static const QString SliperStyle=R"(
        .ElementGraphicsView QScrollBar:vertical{
            background:#FFFFF9;
            width:16px; /*滚动条整体的宽度*/
            margin:5px 0px 5px 0px;
        }
        .ElementGraphicsView QScrollBar::handle:vertical{
            background:rgba(50,50,50,100);
            border-radius:6px;/*圆角*/
            margin:0px 5px 0px 5px;
        }
        .ElementGraphicsView QScrollBar::handle:vertical:hover{
            background:rgba(50,50,50,130);
            border-radius:4px;
            margin:0px 3px 0px 3px;
        }
        .ElementGraphicsView QScrollBar::add-line:vertical{
            background:rgba(50,50,50,100);
        }
        .ElementGraphicsView QScrollBar::sub-line:vertical{
            background:rgba(50,50,50,100);
        }

        .ElementGraphicsView QScrollBar:horizontal{
            background:#FFFFF9;
            height:16px; /*滚动条整体的宽度*/
            margin:0px 5px 0px 5px;
        }

        .ElementGraphicsView QScrollBar::handle:horizontal{
            background:#dbdbdb;
            border-radius:6px;
            margin:5px 0px 5px 0px;
        }
        .ElementGraphicsView QScrollBar::handle:horizontal:hover{
            background:rgba(50,50,50,130);
            border-radius:4px;
            margin:3px 0px 3px 0px;
        }
        .ElementGraphicsView QScrollBar::add-line:horizontal{
            background:rgba(50,50,50,100);
        }
        .ElementGraphicsView QScrollBar::sub-line:horizontal{
            background:rgba(50,50,50,100);
        }
        .ElementGraphicsView{background-color: rgb(255, 255, 255);}
    )";
    setStyleSheet(SliperStyle);
}
